package com.yang.core.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

/**
 * RestClient配置属性类
 * 支持开箱即用的自动配置
 */
@Data
@Component
@ConfigurationProperties(prefix = "restclient")
public class RestClientProperties {

    /**
     * 基础配置
     */
    private Basic basic = new Basic();

    /**
     * 超时配置
     */
    private Timeout timeout = new Timeout();

    /**
     * 重试配置
     */
    private Retry retry = new Retry();

    /**
     * 连接池配置
     */
    private Pool pool = new Pool();

    /**
     * 代理配置
     */
    private Proxy proxy = new Proxy();

    /**
     * SSL配置
     */
    private Ssl ssl = new Ssl();

    /**
     * 监控配置
     */
    private Monitoring monitoring = new Monitoring();

    /**
     * 缓存配置
     */
    private Cache cache = new Cache();

    /**
     * 压缩配置
     */
    private Compression compression = new Compression();

    /**
     * 认证配置
     */
    private Auth auth = new Auth();

    /**
     * 扩展配置
     */
    private Map<String, Object> extensions = new HashMap<>();

    @Data
    public static class Basic {
        /**
         * 基础URL
         */
        private String baseUrl = "";

        /**
         * 默认请求头
         */
        private Map<String, String> defaultHeaders = new HashMap<>();

        /**
         * User-Agent
         */
        private String userAgent = "RestClient/2.0";

        /**
         * 字符编码
         */
        private String charset = "UTF-8";

        /**
         * 是否遵循重定向
         */
        private boolean followRedirects = true;

        /**
         * 是否启用自动发现
         */
        private boolean autoDiscovery = true;
    }

    @Data
    public static class Timeout {
        /**
         * 连接超时
         */
        private Duration connect = Duration.ofSeconds(5);

        /**
         * Socket超时
         */
        private Duration socket = Duration.ofSeconds(10);

        /**
         * 请求超时
         */
        private Duration request = Duration.ofSeconds(15);

        /**
         * 连接请求超时
         */
        private Duration connectionRequest = Duration.ofSeconds(3);
    }

    @Data
    public static class Retry {
        /**
         * 是否启用重试
         */
        private boolean enabled = true;

        /**
         * 最大重试次数
         */
        private int maxAttempts = 3;

        /**
         * 初始延迟
         */
        private Duration initialDelay = Duration.ofMillis(1000);

        /**
         * 退避倍数
         */
        private double backoffMultiplier = 2.0;

        /**
         * 最大延迟
         */
        private Duration maxDelay = Duration.ofSeconds(30);

        /**
         * 重试条件
         */
        private String retryOn = "TIMEOUT,CONNECTION_ERROR,SERVER_ERROR";
    }

    @Data
    public static class Pool {
        /**
         * 最大连接数
         */
        private int maxTotal = 200;

        /**
         * 每个路由最大连接数
         */
        private int maxPerRoute = 50;

        /**
         * 连接验证时间
         */
        private Duration validateAfterInactivity = Duration.ofSeconds(2);

        /**
         * 连接TTL
         */
        private Duration timeToLive = Duration.ofMinutes(5);

        /**
         * 空闲连接超时
         */
        private Duration timeToEvict = Duration.ofMinutes(1);
    }

    @Data
    public static class Proxy {
        /**
         * 是否启用代理
         */
        private boolean enabled = false;

        /**
         * 代理主机
         */
        private String host = "localhost";

        /**
         * 代理端口
         */
        private int port = 8080;

        /**
         * 代理类型
         */
        private Type type = Type.HTTP;

        /**
         * 认证用户名
         */
        private String username = "";

        /**
         * 认证密码
         */
        private String password = "";

        /**
         * 不使用代理的主机
         */
        private String[] nonProxyHosts = {"localhost|127.*|[::1]|0.0.0.0|[::0]"};

        public enum Type {
            HTTP, HTTPS, SOCKS
        }
    }

    @Data
    public static class Ssl {
        /**
         * 是否信任所有证书
         */
        private boolean trustAll = false;

        /**
         * 密钥库路径
         */
        private String keyStorePath = "";

        /**
         * 密钥库密码
         */
        private String keyStorePassword = "";

        /**
         * 密钥库类型
         */
        private String keyStoreType = "JKS";

        /**
         * 信任库路径
         */
        private String trustStorePath = "";

        /**
         * 信任库密码
         */
        private String trustStorePassword = "";

        /**
         * 信任库类型
         */
        private String trustStoreType = "JKS";

        /**
         * 主机名验证
         */
        private boolean hostnameVerification = true;

        /**
         * 支持的协议
         */
        private String[] enabledProtocols = {"TLSv1.2", "TLSv1.3"};

        /**
         * 支持的密码套件
         */
        private String[] enabledCipherSuites = {};
    }

    @Data
    public static class Monitoring {
        /**
         * 是否启用监控
         */
        private boolean enabled = true;

        /**
         * 是否记录请求日志
         */
        private boolean logRequests = true;

        /**
         * 是否记录响应日志
         */
        private boolean logResponses = true;

        /**
         * 是否记录请求体
         */
        private boolean logRequestBody = false;

        /**
         * 是否记录响应体
         */
        private boolean logResponseBody = false;

        /**
         * 日志级别
         */
        private String logLevel = "INFO";

        /**
         * 是否启用指标收集
         */
        private boolean metricsEnabled = true;

        /**
         * 指标前缀
         */
        private String metricsPrefix = "restclient";

        /**
         * 是否启用性能监控
         */
        private boolean performanceMonitoring = true;
    }

    @Data
    public static class Cache {
        /**
         * 是否启用缓存
         */
        private boolean enabled = false;

        /**
         * 缓存类型
         */
        private Type type = Type.MEMORY;

        /**
         * 默认TTL
         */
        private Duration defaultTtl = Duration.ofMinutes(5);

        /**
         * 最大条目数
         */
        private int maxEntries = 1000;

        /**
         * 缓存键生成策略
         */
        private String keyStrategy = "DEFAULT";

        /**
         * Redis配置（当类型为REDIS时）
         */
        private Redis redis = new Redis();

        public enum Type {
            MEMORY, REDIS, CAFFEINE
        }

        @Data
        public static class Redis {
            /**
             * Redis主机
             */
            private String host = "localhost";

            /**
             * Redis端口
             */
            private int port = 6379;

            /**
             * Redis密码
             */
            private String password = "";

            /**
             * Redis数据库
             */
            private int database = 0;

            /**
             * 键前缀
             */
            private String keyPrefix = "restclient:";
        }
    }

    @Data
    public static class Compression {
        /**
         * 是否启用压缩
         */
        private boolean enabled = true;

        /**
         * 支持的压缩算法
         */
        private String[] algorithms = {"gzip", "deflate"};

        /**
         * 压缩阈值（字节）
         */
        private int threshold = 1024;
    }

    @Data
    public static class Auth {
        /**
         * 认证类型
         */
        private Type type = Type.NONE;

        /**
         * Bearer Token
         */
        private String bearerToken = "";

        /**
         * Basic认证用户名
         */
        private String basicUsername = "";

        /**
         * Basic认证密码
         */
        private String basicPassword = "";

        /**
         * API Key
         */
        private String apiKey = "";

        /**
         * OAuth2配置
         */
        private OAuth2 oauth2 = new OAuth2();

        public enum Type {
            NONE, BASIC, BEARER, API_KEY, OAUTH2
        }

        @Data
        public static class OAuth2 {
            /**
             * Token端点
             */
            private String tokenUri = "";

            /**
             * 客户端ID
             */
            private String clientId = "";

            /**
             * 客户端密钥
             */
            private String clientSecret = "";

            /**
             * 授权范围
             */
            private String scope = "";

            /**
             * 用户名
             */
            private String username = "";

            /**
             * 密码
             */
            private String password = "";

            /**
             * 授权类型
             */
            private String grantType = "client_credentials";
        }
    }
}